package controller

import (
	"mini_wms/app/model"

	"github.com/labstack/gommon/log"
	"gorm.io/gorm"

	"mini_wms/app/request"

	"strconv"
	"time"

	"github.com/tealeg/xlsx"

	"errors"
)

type ProductManagement struct{
	Base
}

func NewProductManagement() *ProductManagement{
	return &ProductManagement{}
}


func (c *ProductManagement) GetProductList(productCodeReq string) Res{
	log.Info("GetProductList ProductManagement")
	log.Info("queryParam: " + productCodeReq)
	var list []model.ProductManagement
	if productCodeReq == "" {
		log.Info("GetProductList productCodeReq is null")
		if err := c.db().Where("del_flag = 0").Order("create_time DESC").Find(&list).Error; err!= nil {
			c.log(err.Error())
			return c.error("未查询到产品数据")
		}
	}else {
		productCode := "%" + productCodeReq + "%"
		log.Info("GetProductList productCodeReq is " + productCode)
		if err := c.db().Where("del_flag = 0 and product_code LIKE?",productCode).Order("create_time DESC").Find(&list).Error; err!= nil {
			c.log(err.Error())
			return c.error("未查询到产品数据")
		}
	}
	log.Info("产品记录数：", len(list))
	return c.success(list)
}

func (c *ProductManagement) GeProductById(id string) Res{
	log.Info("GetById ProductManagement")
	var list []model.ProductManagement
	if err := c.db().Find(&list).Error; err != nil {
		c.log(err.Error())
		return c.error("未查询到产品数据")
	}
	
	return c.success(list)
}

func (c *ProductManagement) AddProduct(productReq request.ProductManagementReq) Res{
	log.Info("Add ProductManagement")
	var product model.ProductManagement = ProductReqToProduct(productReq)
	product.CreateBy = "Admin"
	product.CreateTime = time.Now().Format("2006-01-02 15:04:05")
	if err := c.db().Create(&product).Error; err != nil {
		c.log(err.Error())
		return c.error("添加失败")
	}
	return c.success(nil)
}

func  (c *ProductManagement) EditProduct(productReq request.ProductManagementReq) Res{
	log.Info("Edit ProductManagement")
	log.Info("Edit ProductManagement product ID: ", productReq.ID)
	var product model.ProductManagement = ProductReqToProduct(productReq)
	product.UpdateBy = "Admin"
	product.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	err := c.db().Transaction(func(tx *gorm.DB) error {
		if err := tx.Save(&product).Error; err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		c.log(err.Error())
		return c.error("更新失败")
	}
	return c.success(nil)
}

func  (c *ProductManagement) DeleteProduct(productManagement model.ProductManagement) Res{
	log.Info("Delete ProductManagement")
	log.Info(productManagement.ID)
	if err := c.db().Model(&productManagement).Update("del_flag", 1).Error; err != nil {
		c.log(err.Error())
		return c.error("删除失败")
	}
	return c.success(nil)
}

func (c *ProductManagement)  DeleteBatchProduct(id []string) Res{
	log.Info("DeleteBatch ProductManagement")
	return c.success(nil)
}

func (c *ProductManagement) ExportProductOutput() Res {
	log.Info("Export ProductOutput")
	var list []model.ProductOutput
	if err := c.db().Find(&list).Error; err != nil {
		c.log(err.Error())
		return c.error("未查询到产品出货数据")
	}
	file := xlsx.NewFile()
	sheet, err := file.AddSheet("产品出货")
	if err != nil {
		log.Error("ProductManagement Export Error:", err)
		return c.error(err.Error())
	}
	rowTitle := sheet.AddRow()
	cellProductCode := rowTitle.AddCell()
	cellProductCode.Value = "成品货号"
	cellProductSku := rowTitle.AddCell()
	cellProductSku.Value = "成品SKU"
	cellOutboundQuantity := rowTitle.AddCell()
	cellOutboundQuantity.Value = "出货量"
	cellRemark := rowTitle.AddCell()
	cellRemark.Value = "备注"
	cellCreateTime := rowTitle.AddCell()
	cellCreateTime.Value = "创建日期"
	for _, product := range list {
		row := sheet.AddRow()
		cellProductCode := row.AddCell()
		cellProductCode.Value = product.ProductCode
		cellProductSku := row.AddCell()
		cellProductSku.Value = product.ProductSku
		cellOutboundQuantity := row.AddCell()
		cellOutboundQuantity.Value = strconv.Itoa(product.OutboundQuantity)
		cellRemark := row.AddCell()
		cellRemark.Value = product.Remark
		cellCreateTime := rowTitle.AddCell()
		cellCreateTime.Value = product.CreateTime
	}
	appPath := c.pathExist(c.getAppPath() + "/outputFile")
	log.Info("appPath: ", appPath)
	file.Save(appPath + "/产品出货报表.xlsx")
	return c.success(nil)
}

func  (c *ProductManagement) ExportProduct() Res {
	log.Info("Export ProductManagement")
	var list []model.ProductManagement
	if err := c.db().Where("del_flag = 0").Find(&list).Error; err != nil {
		c.log(err.Error())
		return c.error("未查询到产品数据")
	}
	file := xlsx.NewFile()
	sheet, err := file.AddSheet("产品")
	if err != nil {
		log.Error("ProductManagement Export Error:", err)
		return c.error(err.Error())
	}
	rowTitle := sheet.AddRow()
	cellProductCode := rowTitle.AddCell()
	cellProductCode.Value = "成品货号"
	cellProductSku := rowTitle.AddCell()
	cellProductSku.Value = "成品SKU"
	cellProductCategory := rowTitle.AddCell()
	cellProductCategory.Value = "产品类别"
	cellTargetMarket := rowTitle.AddCell()
	cellTargetMarket.Value = "目标商场"
	cellInventory := rowTitle.AddCell()
	cellInventory.Value = "当前余量"
	cellRemark := rowTitle.AddCell()
	cellRemark.Value = "备注"
	cellCreateTime := rowTitle.AddCell()
	cellCreateTime.Value = "创建日期"
	cellUpdateTime := rowTitle.AddCell()
	cellUpdateTime.Value = "更新日期"

	for _, product := range list {
		row := sheet.AddRow()
		cellProductCode := row.AddCell()
		cellProductCode.Value = product.ProductCode
		cellProductSku := row.AddCell()
		cellProductSku.Value = product.ProductSku
		cellProductCategory := row.AddCell()
		cellProductCategory.Value =  product.ProductCategory
		cellTargetMarket := row.AddCell()
		cellTargetMarket.Value = product.TargetMarket
		cellInventory := row.AddCell()
		cellInventory.Value = strconv.Itoa(product.Inventory)
		cellRemark := row.AddCell()
		cellRemark.Value = product.Remark
		cellCreateTime := rowTitle.AddCell()
		cellCreateTime.Value = product.CreateTime
		cellUpdateTime := rowTitle.AddCell()
		cellUpdateTime.Value = product.UpdateTime
	}
	appPath := c.pathExist(c.getAppPath() + "/outputFile")
	log.Info("appPath: ", appPath)
	file.Save(appPath + "/产品管理报表.xlsx")
	return c.success(nil)
}

func  (c *ProductManagement) ImportProduct(filePath string) Res{
	log.Info("Import ProductManagement info: " + filePath)
	var list [] model.ProductManagement
	if err := c.db().Where("del_flag = 0").Find(&list).Error; err != nil {
	}
	productMap := map[string]string{}
	for _, product := range list {
		productMap[product.ProductCode] = product.ProductSku
	}
	xlFile, err := xlsx.OpenFile(filePath)
	if err != nil {
		return c.error(err.Error())
	}
	productSheet := xlFile.Sheets[0]
	if productSheet == nil {
		return c.error("未找到产品导入文件")
	}
	rowTitle := productSheet.Rows[0]
	if rowTitle == nil || rowTitle.Cells == nil || rowTitle.Cells[0].Value!= "成品货号" {
		return c.error("未找到产品导入文件")
	}

	var productExcelList [] model.ProductManagement
	for _, row := range productSheet.Rows[1:] {
		var product model.ProductManagement
		if row.Cells[0].Value == "" {
			continue
		}
		if _, ok := productMap[row.Cells[0].Value]; ok {
			continue
		}
		for i := 0; i < len(row.Cells); i++ {
			switch i {
			case 0:
				product.ProductCode = row.Cells[i].Value
			case 1:
				product.ProductSku = row.Cells[i].Value
			case 2:
				product.ProductCategory = row.Cells[i].Value
			case 3:
				product.TargetMarket = row.Cells[i].Value
			case 4:
				inventory, err := strconv.Atoi(row.Cells[i].Value)
				if err!= nil {
					inventory = 0
				}
				product.Inventory = inventory
			case 5:
				product.Remark = row.Cells[i].Value
			}
		}
		product.CreateBy = "Admin"
		product.CreateTime = time.Now().Format("2006-01-02 15:04:05")
		productExcelList = append(productExcelList, product)
	}
	if err := c.db().Create(&productExcelList).Error; err != nil {
		c.log(err.Error())
		return c.error("添加失败")
	}
	return c.success(nil)
}


func (c *ProductManagement) DownloadProductTemplate() Res {
	log.Info("DownloadTemplate ProductManagement")
	file := xlsx.NewFile()
	sheet, err := file.AddSheet("产品导入模板")
	if err != nil {
		log.Error("ProductManagement DownloadProductTemplate Error:", err)
		return c.error("下载模板失败")
	}
	rowTitle := sheet.AddRow()
	cellProductCode := rowTitle.AddCell()
	cellProductCode.Value = "成品货号"
	cellProductSku := rowTitle.AddCell()
	cellProductSku.Value = "成品SKU"
	cellProductCategory := rowTitle.AddCell()
	cellProductCategory.Value = "产品类别"
	cellTargetMarket := rowTitle.AddCell()
	cellTargetMarket.Value = "目标商场"
	cellInventory := rowTitle.AddCell()
	cellInventory.Value = "当前余量"
	cellRemark := rowTitle.AddCell()
	cellRemark.Value = "备注"

	appPath := c.pathExist(c.getAppPath() + "/outputFile")
	log.Info("appPath: ", appPath)
	errSave := file.Save(appPath + "/产品导入模板.xlsx")
	if errSave!= nil {
		log.Error("ProductManagement DownloadProductTemplate Save Error:", errSave)
		return c.error("下载模板失败")
	}
	return c.success(nil)
}

func (c *ProductManagement) GetProductOutputList(productCodeReq string) Res{
	log.Info("GetProductOutputList ProductManagement")
	log.Info("queryParam: " + productCodeReq)
	var list []model.ProductOutput
	if productCodeReq == "" {
		log.Info("GetProductOutputList productCodeReq is null")
		if err := c.db().Order("create_time DESC").Find(&list).Error; err!= nil {
			c.log(err.Error())
			return c.error("未查询到产品数据")
		}
	}else {
		productCode := "%" + productCodeReq + "%"
		log.Info("GetProductOutputList productCodeReq is " + productCode)
		if err := c.db().Where("product_code LIKE?",productCode).Order("create_time DESC").Find(&list).Error; err!= nil {
			c.log(err.Error())
			return c.error("未查询到产品数据")
		}
	}
	return c.success(list)
}

func (c *ProductManagement) AddProductOutput(productOutputReq request.ProductOutputReq) Res{
	log.Info("Add ProductOutput")
	var productOutput model.ProductOutput = ProductOutputReqToProductOutput(productOutputReq)
	productOutput.CreateBy = "Admin"
	productOutput.CreateTime = time.Now().Format("2006-01-02 15:04:05")

	var listProductBOM []model.ProductBOM
	productId := productOutput.ID
	log.Info("ProductOutput ID: ", productId)
	if err := c.db().Where("product_id = ?",productId).Find(&listProductBOM).Error; err != nil {
		c.log(err.Error())
		return c.error("未查询到产品BOM数据")
	}
	outboundQuantity := productOutput.OutboundQuantity
	if(outboundQuantity <= 0){
		return c.error("出库数量错误")
	}
	partQuantityMap := map[int]int{}
	for _, productBOM := range listProductBOM {
		partOutboundQuantity := productBOM.PartQuantity * outboundQuantity
		partQuantityMap[productBOM.PartID] = partOutboundQuantity
	}
	errorT := c.db().Transaction(func(tx *gorm.DB) error{
		log.Info("ProductOutput partQuantityMap len: ", len(partQuantityMap))
		for key, value := range partQuantityMap {
			var part model.PartManagement = model.PartManagement{}
			tx.First(&part,key)
			log.Info("ProductOutput part ID: ", part.ID)
			part.Inventory = part.Inventory - value
			if part.Inventory < 0 {
				return errors.New("库存不足")
			}
			part.UpdateBy = "Admin"
			part.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
			if err := tx.Save(&part).Error; err != nil {
				return err
			}
			partInput := PartToPartInput(part)
			partInput.InventoryQuantity = value
			partInput.CreateBy = "Admin"
			partInput.CreateTime = time.Now().Format("2006-01-02 15:04:05")
			partInput.InputType = 2
			if err := tx.Create(&partInput).Error; err != nil {
				return err
			}
		} 

		var product model.ProductManagement = model.ProductManagement{}
		if err := tx.First(&product,productId).Error; err!= nil {
			c.log(err.Error())
			return err
		}
		product.Inventory = product.Inventory + outboundQuantity
		product.UpdateBy = "Admin"
		product.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
		if err := tx.Save(&product).Error; err!= nil {
			c.log(err.Error())
			return err
		}
		if err := tx.Create(&productOutput).Error; err!= nil {
			c.log(err.Error())
			return err
		}
		return nil
	})
	if errorT!= nil {
		c.log(errorT.Error())
		return c.error("出库失败: " + errorT.Error())
	}
	return c.success(nil)
}

func ProductReqToProduct(productReq request.ProductManagementReq) model.ProductManagement {
	var product model.ProductManagement = model.ProductManagement{}
	if productReq.ID != 0 {
		product.ID = productReq.ID
	}
	product.ProductCode = productReq.ProductCode
	product.ProductSku = productReq.ProductSku
	product.ProductCategory = productReq.ProductCategory
	product.TargetMarket = productReq.TargetMarket
	inventory,err := strconv.Atoi(productReq.Inventory) 
	if(err != nil){
		log.Error("PartReqToPart Error:", err)
	}
	product.Inventory = inventory
	product.Remark = productReq.Remark
	product.CreateBy = productReq.CreateBy
	product.CreateTime = productReq.CreateTime
	product.UpdateBy = productReq.UpdateBy
	product.UpdateTime = productReq.UpdateTime
	return product
}

func ProductOutputReqToProductOutput(productOutputReq request.ProductOutputReq) model.ProductOutput {
	var productOutput model.ProductOutput = model.ProductOutput{}
	if productOutputReq.ID != 0 {
		productOutput.ID = productOutputReq.ID
	}
	productOutput.ProductCode = productOutputReq.ProductCode
	productOutput.ProductSku = productOutputReq.ProductSku
	outboundQuantity,err := strconv.Atoi(productOutputReq.OutboundQuantity)
	if(err != nil){
		log.Error("ProductOutputReqToProductOutput Error:", err)
	}
	productOutput.OutboundQuantity = outboundQuantity
	productOutput.Remark = productOutputReq.Remark
	return productOutput
}
